﻿using FPSO.HMI.Controls;
using FPSO.HMI.Utils;
using FPSO.HMI.Views.Dialog;
using FPSO.Models.Constant;
using FPSO.Models.Domain;
using FPSO.Services.Impl;
using SafeLoad.NControl.Assist;
using SafeLoad.NControl;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using static FPSO.Models.Constant.TankConstant;

namespace FPSO.HMI.Views
{
    /// <summary>
    /// OutAndSwapView.xaml 的交互逻辑
    /// </summary>
    public partial class OutAndSwapView : UserControl
    {
        Thread taskThread = null;
        bool running = true;
		private DispatcherTimer taskTimer;
		private DispatcherTimer updateTaskQueueTimer;

		//simuTaskTimer为临时下发任务的计时器，用于监控任务状态
		//为防止下发任务始终没有达到目标值，计时器无法停止，设置任务执行时间
		private DispatcherTimer simuTaskTimer = null;
		private int simuTaskTick = 0;
		private int maxSimuTaskTick = 180;
		private int simuTaskTimeSpan = 20;

		public OutAndSwapView()
        {
            InitializeComponent();
            // 定义图表字段
            // 强度
            strengthLine.SetCurve("剪力", null, Colors.DodgerBlue);
			strengthLine.SetCurve("弯矩", null, Colors.DarkOrange);
            // 舯吃水
            draftLine.SetCurve("计算舯吃水", null, Colors.DodgerBlue);
			draftLine.SetCurve("实际舯吃水", null, Colors.Yellow);
			// 横纵倾
			heelTrimLine.SetCurve("横倾", null, Colors.DodgerBlue);
            heelTrimLine.SetCurve("纵倾", null, Colors.DarkOrange);
            // 初稳性高
            stabilityLine.SetCurve("初稳性高", null, Colors.DodgerBlue);

			taskTimer = new DispatcherTimer();
			taskTimer.Interval = TimeSpan.FromSeconds(1);
			taskTimer.Tick += TaskTimer_Tick;
			taskTimer.Start();
			//taskQueue.TaskService = new DBTankTaskService();
			//taskThread = new Thread(UpdateUITask);
   //         taskThread.IsBackground = true;
   //         taskThread.Start();

            updateTaskQueueTimer = new DispatcherTimer();
            updateTaskQueueTimer.Interval = TimeSpan.FromMilliseconds(600000);
            updateTaskQueueTimer.Tick += TaskQueueTimer_Tick;
            updateTaskQueueTimer.Start();
        }

        
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            if (!outAndSwap.IsInitBindingService())
            {
                outAndSwap.StartReal();
            }
        }

		private void TaskTimer_Tick(object sender, EventArgs e)
		{
			//待测试
			outAndSwap.SetImitateTime(DateTime.Now);
		}

		private void TaskQueueTimer_Tick(object sender, EventArgs e)
        {
            Dictionary<string, double> currentVolmDic0 = outAndSwap.GetTankVolumeDic();
            //taskQueue.ControlUpdateByRata(currentVolmDic0);
        }

        public void ReloadTaskQueue()
        {
            //taskQueue.ControlUpdate();
        }

		private void outAndSwap_OnAddTankTask(string srcTankId)
		{
			TankLoadTypeSelectDialog tankLoadTypeSelectDialog = new TankLoadTypeSelectDialog();
			if (tankLoadTypeSelectDialog.ShowDialog() == true)
			{
				if (tankLoadTypeSelectDialog.LoadTypeSelect == 1)
				{
					//DEBUG 这里仿照压载倒舱，点击可制定货油注入任务，原先制定计划的过程暂时封掉
					Dictionary<string, double> currentVolmDic0 = outAndSwap.GetTankVolumeDic();
					COTLoadTaskDialog loadTaskDialog = new COTLoadTaskDialog(srcTankId, currentVolmDic0, false);
					if (loadTaskDialog.ShowDialog() == true)
					{
						List<ConstantTankInfo> taskInfos = TankConstant.getCOTTank();
						Dictionary<string, double> taskTankVolume = currentVolmDic0;
						string tar_tankName = loadTaskDialog.g_TargetTank;
						double adjustvol = loadTaskDialog.g_Adjustvol;
						Int16 srctankno = 0;
						for (int i = 0; i < taskInfos.Count; i++)
						{
							ConstantTankInfo info = taskInfos[i];
							string tankname = info.TankName;
							if (tankname == srcTankId)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] += adjustvol;
								srctankno = Convert.ToInt16(i + 1);
								break;
							}
						}
						SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
						ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
						if (calcResult.GetShipCheckStatus() == true)
						{
							//再次确认
							var dialgoResult = MessageBox.Show("完成货油注入任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
							if (dialgoResult == MessageBoxResult.Yes)
							{
								double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
								Int16 readflag = 2;
								Int16 tanktype = 0;
								Int16 taskop = 1;

								string taskpre = "Task1CTInstructCache[0]";
								string tag0 = "ReadFlag";
								string tag1 = "sourceTkNo";
								string tag2 = "targetTkNo";
								string tag3 = "TkType";
								string tag4 = "TargetLevel";
								string tag5 = "TaskOp";
								string tag_start = "HmiTask1CTInstructStartCmd";
								string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
								string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
								string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
								string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
								string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
								string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
								string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								//注入没有原舱，代码以0代替
								App.UaClient.WriteNode<Int16>(status_tag1, 0);
								App.UaClient.WriteNode<Int16>(status_tag2, srctankno);
								App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
								//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
								App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
								App.UaClient.WriteNode<Int16>(status_tag5, taskop);

								dialgoResult = MessageBox.Show("完成货油注入任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
								if (dialgoResult == MessageBoxResult.Yes)
								{
									App.UaClient.WriteNode<Int16>(status_tag0, readflag);
									App.UaClient.WriteNode<Boolean>(status_tag_start, true);

									string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M", srcTankId, srctanklevel);
									CommUtil.AddSystemLog(6, 0, info);
									simuTaskTimer = new DispatcherTimer();
									simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
									simuTaskTimer.Tick += SimuTaskTimer_Tick1;
									simuTaskTimer.Tag = string.Format("{0}:{1:N3}", srcTankId, srctanklevel);
									simuTaskTick = 0;
									simuTaskTimer.Start();
								}
							}
						}
					}
				}
				else if (tankLoadTypeSelectDialog.LoadTypeSelect == 2)
				{
					//DEBUG 双击主界面设置舱室调载目标的交互暂时封掉
					Dictionary<string, double> currentVolmDic0 = outAndSwap.GetTankVolumeDic();
					Dictionary<string, double> currentLevelDic0 = outAndSwap.GetTankInnDic();
					WBTSwapTaskDialog wBTSwapTaskDialog = new WBTSwapTaskDialog(srcTankId, currentVolmDic0, currentLevelDic0, false);
					if (wBTSwapTaskDialog.ShowDialog() == true)
					{
						List<ConstantTankInfo> taskInfos = TankConstant.getCOTTank();
						Dictionary<string, double> taskTankVolume = currentVolmDic0;
						string tar_tankName = wBTSwapTaskDialog.g_TargetTank;
						double adjustvol = wBTSwapTaskDialog.g_Adjustvol;
						bool heelChecked = wBTSwapTaskDialog.g_HeelChecked;
						Int16 srctankno = 0;
						Int16 tartankno = 0;
						for (int i = 0; i < taskInfos.Count; i++)
						{
							ConstantTankInfo info = taskInfos[i];
							string tankname = info.TankName;
							if (tankname == srcTankId)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] -= adjustvol;
								srctankno = Convert.ToInt16(i + 1);
							}
							else if (tankname == tar_tankName)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] += adjustvol;
								tartankno = Convert.ToInt16(i + 1);
							}
						}

						SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
						ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
						if (calcResult.GetShipCheckStatus() == true)
						{
							//再次确认
							var dialgoResult = MessageBox.Show("完成倒舱任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
							if (dialgoResult == MessageBoxResult.Yes)
							{
								double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
								double tartanklevel = calcResult.GetTankCalcStateByName(tar_tankName).Inn;
								Int16 readflag = 2;
								Int16 tanktype = 0;
								Int16 taskop = 3;

								string taskpre = "Task3CTInstructCache[0]";
								string tag0 = "ReadFlag";
								string tag1 = "sourceTkNo";
								string tag2 = "targetTkNo";
								string tag3 = "TkType";
								string tag4 = "TargetLevel";
								string tag5 = "TaskOp";
								string tag_start = "HmiTask3CTInstructStartCmd";
								string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
								string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
								string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
								string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
								string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
								string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
								string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								App.UaClient.WriteNode<Int16>(status_tag1, srctankno);
								App.UaClient.WriteNode<Int16>(status_tag2, tartankno);
								App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
								App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
								//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(tartanklevel));
								App.UaClient.WriteNode<Int16>(status_tag5, taskop);

								dialgoResult = MessageBox.Show("完成倒舱任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
								if (dialgoResult == MessageBoxResult.Yes)
								{
									App.UaClient.WriteNode<Int16>(status_tag0, readflag);
									App.UaClient.WriteNode<Boolean>(status_tag_start, true);

									simuTaskTimer = new DispatcherTimer();
									simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
									simuTaskTimer.Tick += SimuTaskTimer_Tick1;
									string info = string.Format("排载舱室：[{0}] 目标液位[{1:N3}]M，压载舱室：[{2}] 目标液位[{3:N3}]M",
									srcTankId, srctanklevel, tar_tankName, tartanklevel);
									CommUtil.AddSystemLog(6, 0, info);
									simuTaskTimer.Tag = string.Format("{0}:{1:N3}", tar_tankName, tartanklevel);
									simuTaskTick = 0;
									simuTaskTimer.Start();
									return;
								}
							}
						}
					}
				}
			}
		}
		private void SimuTaskTimer_Tick1(object sender, EventArgs e)
		{
			string tag = Convert.ToString(simuTaskTimer.Tag);
			Dictionary<string, double> currentVolmDic0 = outAndSwap.GetTankVolumeDic();
			SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
			ManualCalcResult calcResult = algorithmService.CallManualCalc(currentVolmDic0, 3);

			bool check = true;
			string tar_tankname = tag.Split(':')[0];
			double tar_tanklevel = Convert.ToDouble(tag.Split(':')[1]);
			double cur_tanklevel = calcResult.GetTankCalcStateByName(tar_tankname).Inn;
			string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M，当前液位[{2:N3}]M",
				tar_tankname, tar_tanklevel, cur_tanklevel);
			CommUtil.AddSystemLog(6, 0, info);

			if (cur_tanklevel >= tar_tanklevel)
			{
				check = false;
				CommUtil.AddSystemLog(6, 0, "调载完成");
			}

			simuTaskTick++;
			if (simuTaskTick > maxSimuTaskTick)
				check = false;

			if (!check)
			{
				//此处需要向下位机发送终止当前过程的命令
				//string tag_stop = "HMITaskStopCmd";
				//string status_tag0 = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_stop);
				//App.UaClient.WriteNode<Boolean>(status_tag0, true);
				simuTaskTimer.Stop();
			}
		}

		public void SetShipDraught(ShipDraught calcDraught, ShipDraught realDraught)
        {
            //shipInfo.SetShipInfo(calcDraught, realDraught);
        }

        /// <summary>
        /// 添加强度数据
        /// </summary>
        /// <param name="sf">剪力</param>
        /// <param name="bm">弯矩</param>
        public void AddStrengthData(double sf, double bm)
        {
            this.Dispatcher.Invoke(new Action(() => {
				// 添加图表数值标记信息
                CreateMarkText(strengthLine, "剪力", "弯矩", sf, bm, 85, 85,true);
                strengthLine.AddCurveData(new string[] { "剪力", "弯矩" }, new double[] { sf, bm });
            }));
        }

        /// <summary>
        /// 添加舯吃水数据
        /// </summary>
        /// <param name="draft">舯吃水</param>
        public void AddDraftLineData(double calc_draft,double real_draft)
        {
            this.Dispatcher.Invoke(new Action(() => {
                // 添加图表数值标记信息
                CreateMarkText(draftLine, "计算舯吃水", "实际舯吃水", calc_draft, real_draft, 16.7, 16.7, true);
                draftLine.AddCurveData(new string[] { "计算舯吃水","实际舯吃水" }, new double[] { calc_draft, real_draft });
            }));
        }

        /// <summary>
        /// 添加横纵倾数据
        /// </summary>
        /// <param name="hell">横倾</param>
        /// <param name="trim">纵倾</param>
        public void AddHeelTrimData(double hell, double trim)
        {
            this.Dispatcher.Invoke(new Action(() => {
                // 添加图表数值标记信息
                CreateMarkText(heelTrimLine, "横倾", "纵倾", hell, trim, 2, 2, true);
                heelTrimLine.AddCurveData(new string[] { "横倾", "纵倾" }, new double[] { hell, trim });
            }));
        }

        /// <summary>
        /// 添加初稳性高数据
        /// </summary>
        /// <param name="stability">初稳性高</param>
        public void AddStabilityData(double stability)
        {
            this.Dispatcher.Invoke(new Action(() => {
				// 添加图表数值标记信息(曲线key值为null时不绘制这条曲线)
				CreateMarkText(stabilityLine, "初稳性高", null, stability, 0, 0.15, 0, false);
                stabilityLine.AddCurveData(new string[] { "初稳性高" }, new double[] { stability });
            }));
        }

        /// <summary>
        /// 打开舱室监控曲线图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OpenMonitor_Click(object sender, RoutedEventArgs e)
        {
            TankMonitorDialog dlg = new TankMonitorDialog();
			dlg.ShowDialog();
        }

		public void SetTankStatus(ManualCalcResult calcResult)
		{
			outAndSwap.SetTankStatus(calcResult);
		}

		/// <summary>
		/// 创建图表标记文本
		/// </summary>
		/// <param name="curve">图表对象</param>
		/// <param name="key1">曲线1关键字</param>
		/// <param name="key2">曲线2关键字</param>
		/// <param name="val1">曲线1新增数值</param>
		/// <param name="val2">曲线2新增数值</param>
		/// <param name="alarm1">曲线1高位预警值</param>
		/// <param name="alarm2">曲线2高位预警值</param>
		/// <param name="MaxLimit">如果是true，则限制值为最大值，否则为最小值</param>

		public void CreateMarkText(NCurve curve, String key1, String key2, Double val1, Double val2, Double alarm1, Double alarm2,bool MaxLimit)
        {
            // 每次添加标记时先清除原有标记文本信息
            curve.RemoveAllMarkText();
            // 添加曲线时进行数值阈值判断，大于高预警值时标签文字颜色变为红色，其余数值为白色
            if (null != key1)
            {
				bool check1 = true;
				if((MaxLimit == true && val1 > alarm1) || (MaxLimit == false && val1 < alarm1))
					check1 = false;
				// 添加曲线1的标记文本
				curve.AddMarkText(new NMarkText
                {
                    CurveKey = key1,
                    Index = curve.GetCurveItem(key1).Data.Length == 0 ? 0 : curve.GetCurveItem(key1).Data.Length - 1,
                    MarkText = val1.ToString(),
                    TextColor = check1 ? Color.FromRgb(255, 255, 255) : Color.FromRgb(255, 0, 0),
                    CircleColor = check1 ? Color.FromRgb(255, 255, 255) : Color.FromRgb(255, 0, 0),
                    PositionStyle = MarkTextPositionStyle.Up
                });
            }
            if (null != key2)
            {
				bool check1 = true;
				if ((MaxLimit == true && val2 > alarm2) || (MaxLimit == false && val2 < alarm2))
					check1 = false;
				// 添加曲线2的标记文本
				curve.AddMarkText(new NMarkText
                {
                    CurveKey = key2,
                    Index = curve.GetCurveItem(key2).Data.Length == 0 ? 0 : curve.GetCurveItem(key2).Data.Length - 1,
                    MarkText = val2.ToString(),
					TextColor = check1 ? Color.FromRgb(255, 255, 255) : Color.FromRgb(255, 0, 0),
					CircleColor = check1 ? Color.FromRgb(255, 255, 255) : Color.FromRgb(255, 0, 0),
                    PositionStyle = MarkTextPositionStyle.Up
                });
            }
            
        }

    }
}
